package com.example.practica3enraya;


import android.os.Bundle;
import android.app.Activity;
import android.graphics.Color;
import android.graphics.PorterDuff;
import android.view.Menu;
import android.widget.Button;
import android.widget.RadioButton;
import android.widget.TextView;

public class MainActivity extends Activity {
	private TextView texto, anuncio;
	public Button A1,A2,A3,B1,B2,B3,C1,C2,C3;
	public RadioButton radioJugadores, radioMaquina;
	private int maquina=0, turno=1, contador=0;
	private int [][] control = {{0,0,0},{0,0,0},{0,0,0}};
	
	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.activity_main);
		MyListener l= new MyListener(this);
		
		texto = (TextView)findViewById(R.id.Texto);
		anuncio = (TextView)findViewById(R.id.Mensaje);
		A1 = (Button)findViewById(R.id.A1);
		A2 = (Button)findViewById(R.id.A2);
		A3 = (Button)findViewById(R.id.A3);
		B1 = (Button)findViewById(R.id.B1);
		B2 = (Button)findViewById(R.id.B2);
		B3 = (Button)findViewById(R.id.B3);
		C1 = (Button)findViewById(R.id.C1);
		C2 = (Button)findViewById(R.id.C2);
		C3 = (Button)findViewById(R.id.C3);
		radioJugadores = (RadioButton)findViewById(R.id.radio1);
		radioMaquina = (RadioButton)findViewById(R.id.radio2);
		
		A1.setOnClickListener(l);
		A2.setOnClickListener(l);
		A3.setOnClickListener(l);
		B1.setOnClickListener(l);
		B2.setOnClickListener(l);
		B3.setOnClickListener(l);
		C1.setOnClickListener(l);
		C2.setOnClickListener(l);
		C3.setOnClickListener(l);
		radioJugadores.setOnClickListener(l);
		radioMaquina.setOnClickListener(l);
		
		A1.getBackground().setColorFilter(Color.BLACK, PorterDuff.Mode.MULTIPLY);
		A2.getBackground().setColorFilter(Color.BLACK, PorterDuff.Mode.MULTIPLY);
		A3.getBackground().setColorFilter(Color.BLACK, PorterDuff.Mode.MULTIPLY);
		B1.getBackground().setColorFilter(Color.BLACK, PorterDuff.Mode.MULTIPLY);
		B2.getBackground().setColorFilter(Color.BLACK, PorterDuff.Mode.MULTIPLY);
		B3.getBackground().setColorFilter(Color.BLACK, PorterDuff.Mode.MULTIPLY);
		C1.getBackground().setColorFilter(Color.BLACK, PorterDuff.Mode.MULTIPLY);
		C2.getBackground().setColorFilter(Color.BLACK, PorterDuff.Mode.MULTIPLY);
		C3.getBackground().setColorFilter(Color.BLACK, PorterDuff.Mode.MULTIPLY);
		
	}
	
	public void accion(Button b){
		if(maquina==1){ //Acciones si se juega contra la maquina
			if(b.getText()=="X"||b.getText()=="O"){
				//Control para un solo cambio
			}else{
					turno=1;
					boolean fin=false;
				 	b.setText("X");
				 	asignarArray(b);
					contador++;// contador para controlar el empate
					turno=2;
					
					if(contador==5)
						fin=true;
					
					comprobarVictoria();
										
					if(fin==false){
						accionMaquina();	
						comprobarVictoria();
					}
			}
		}else if(maquina==2){ //Acciones si se juegan dos jugadores
			if(b.getText()=="X"||b.getText()=="O"){
				//Control para un solo cambio
			}else{
				if(turno==1){
					b.setText("X");
					asignarArray(b);
					texto.setText(this.getString(R.string.turnoO));
					contador++;
					comprobarVictoria();
					turno=2;
			}else{
					b.setText("O");
					asignarArray(b);
					texto.setText(this.getString(R.string.turnoX));
					contador++;
					comprobarVictoria();
					turno=1;}
			}
		}else{
			
		}
	}
	
	//Ejecuta la acción de la maquina, calcula la posicion optima con inteligenciaArtificial() y se ayuda del metodo 
	//ayudaMaquina(Button b) realizar las comprobaciones y a�adir el caracter
	private void accionMaquina(){
		boolean comprobacion=false;
		while(comprobacion==false){
		int valor=inteligenciaArtificial();
		switch (valor) {
			case 0:
				comprobacion=ayudaMaquina(A1);
				break;
			case 1:
				comprobacion=ayudaMaquina(A2);
				break;
			case 2:
				comprobacion=ayudaMaquina(A3);
				break;
			case 3:
				comprobacion=ayudaMaquina(B1);
				break;
			case 4:
				comprobacion=ayudaMaquina(B2);
				break;
			case 5:
				comprobacion=ayudaMaquina(B3);
				break;
			case 6:
				comprobacion=ayudaMaquina(C1);
				break;
			case 7:
				comprobacion=ayudaMaquina(C2);
				break;
			case 8:
				comprobacion=ayudaMaquina(C3);
				break;
			default:
				break;
			}
		}
	}
	
	//Analiza si el boton ya esta usado y si no a�ade el valor correspondiente con el metodo asignarArray (Button b)
	private boolean ayudaMaquina(Button b){
		if(!(b.getText()=="X"||b.getText()=="O")){
			b.setText("O");
			asignarArray(b);
			turno=1;
			return true;
		}
		return false;
	}
	
	//Asigna el correspondiente valor del boton en el array de control:
	private void asignarArray (Button b){
		switch (b.getId()) {
		case R.id.A1: 
			control[0][0]=turno;
			break;
		case R.id.A2: 
			control[0][1]=turno;
			break;
		case R.id.A3: 
			control[0][2]=turno;
			break;
		case R.id.B1: 
			control[1][0]=turno;
			break;
		case R.id.B2: 
			control[1][1]=turno;
			break;
		case R.id.B3: 
			control[1][2]=turno;
			break;
		case R.id.C1: 
			control[2][0]=turno;
			break;
		case R.id.C2: 
			control[2][1]=turno;
			break;
		case R.id.C3: 
			control[2][2]=turno;
			break;
		default:
			break;

		}
	}
	
	//Comprueba el valor de las posibilidades que dan victoria y devuelve el numero del ganador o 0 si no gana nadie.
	public int ganaPartida(){
        if (control[0][0] != 0 && control[0][0] == control[1][1]   && control[0][0] == control[2][2])//Diagonal 1
            return control[0][0];
        if (control[0][2] != 0 && control[0][2] == control[1][1]  && control[0][2] == control[2][0])//Diagonal 2
            return control[0][2];
        for (int n=0;n<=2;n++){
            if (control[n][0] != 0 && control[n][0] == control[n][1] && control[n][0] == control[n][2])//Filas
                return control[n][0];
            if (control[0][n] != 0 && control[0][n] == control[1][n]  && control[0][n] == control[2][n])//Columnas
                return control[0][n];
        }
        return 0;
    }
	
	//Si hay un ganador o se produce empate muestra un mensaje y llama al metodo volverAJugar() para iniciar de nuevo.
	public void comprobarVictoria(){
		int valor=0;	
		valor=ganaPartida();
			if(valor==1){
				texto.setText(this.getString(R.string.ganaX));
				volverAJugar();}
			
			if(valor==2){
				texto.setText(this.getString(R.string.ganaO));
				volverAJugar();}
						
			if (contador==9){ //Devuelve empate si se agotan los intentos en dos jugadores
					texto.setText(this.getString(R.string.empate));
					volverAJugar();}
			
			if (contador==5 & maquina==1){ //Devuelve empate si se agotan los intentos en un jugadores
					texto.setText(this.getString(R.string.empate));
					volverAJugar();}	
	}
		
	private void volverAJugar(){
		//Reinicio de las variables:
		maquina=0;
		contador=0;
		turno=1;
		
		for(int x=0;x<=2;x++)
			for(int y=0;y<=2;y++)
				control[x][y]=0;
		//Cambios de color y de texto
		anuncio.setText(this.getString(R.string.aviso));
		anuncio.setTextColor(Color.WHITE);
		radioJugadores.setClickable(true);
		radioJugadores.setTextColor(Color.WHITE);
		radioMaquina.setClickable(true);
		radioMaquina.setTextColor(Color.WHITE);
		texto.setTextSize(30);
		texto.setTextColor(Color.RED);
	}
	
	public void setMaquina(int jugador){
		maquina=jugador;
		//Cambios de color y texto:
		texto.setText(this.getString(R.string.turnoX));
		anuncio.setText(this.getString(R.string.NoCambioDeJuego));
		anuncio.setTextColor(Color.DKGRAY);
		radioJugadores.setClickable(false);
		radioJugadores.setTextColor(Color.DKGRAY);
		radioMaquina.setClickable(false);
		radioMaquina.setTextColor(Color.DKGRAY);
		texto.setTextSize(20);
		texto.setTextColor(Color.DKGRAY);
		//Reseteo de los botones:
		A1.setText("");
		A2.setText("");
		A3.setText("");
		B1.setText("");
		B2.setText("");
		B3.setText("");
		C1.setText("");
		C2.setText("");
		C3.setText("");
	}
    
    //Serie de algoritmos nececesarios para la Inteligencia artificial:
	
	//Comprueba si el tablero esta completo, devuelve true si esta lleno.
    private boolean tableroCompleto(){
        for (int n=0;n<=2;n++)
            for (int m=0;m<=2;m++)
                if (control[n][m]==0)
                    return false;
        return true;
    }
    
    //Devuelve true si la partida ha finalizado por que se llena el tablero o gana alguien
    private boolean finPartida(){
        return tableroCompleto() || ganaPartida()!= 0;
    }
    
    //algoritmo principal Minimax:
    //
    //Algoritmo de inteligencia artificial basado en la teoria de juegos.
    public int inteligenciaArtificial(){
        int valor=-1;
        int contador=-1;
    	if (!finPartida()){
            int f=0, c=0;
            int v=Integer.MIN_VALUE;
            int aux;
            for (int n=0;n<=2;n++){
                for (int m=0;m<=2;m++){
                    if (control[n][m]==0){
                        control[n][m]=2;
                        aux=min();
                        if (aux>v) {//Cuando la variable aux contieen el valor mas probable asigna esa posicion de array
                            v=aux;
                            f=n; 
                            c=m;
                        }
                        control[n][m]=0;
                    }
                }
            } //Al acabar el for, quedaria en f,c la posición optima para el jugador O.
            //Transforma el array bidimensional en un valor lineal para poder ser devuelto de manera unitaria.
            for (int n=0;n<=2;n++){
                for (int m=0;m<=2;m++){
                	contador++;
                	if(m==c && n==f)
                		valor=contador;
                	}
                }        
        }
    	return valor;
    }
    
    //Algoritmo complementario recursivo para hallar el maximo
    private int max(){
        if (finPartida()){
            if (ganaPartida()!=0) return 0;
            else return 1;
        }
        int v=Integer.MIN_VALUE;
        int aux;
        for (int n=0;n<=2;n++){ //Recorre todas las posibilidades del array
            for (int m=0;m<=2;m++){
                if (control[n][m]==0){ //Si esta vacia
                    control[n][m]=2; //Añade posicion del jugador O
                    aux=min(); //Llama al metodo del jugador X
                    if (aux>v) v=aux; //Cuando se llena el tablero(no se puede llamar a un nuevo metodo, guarda
                    //quien gana en ultima instancia debido al if que hay en la primera linea del metodo, entonces
                    //va subiendo niveles al cerrarse los metodos guardando quien gana si su valor es inferior
                    //al actual.    
                    control[n][m]=0;
                 }
            }
        }
        return v;
    }
    
    //Algoritmo complementario recursivo para hallar el minimo
    private int min(){
        if (finPartida()){
            if (ganaPartida()!=0) return 2;
            else return 1;
        }
        int v=Integer.MAX_VALUE;
        int aux;
        for (int n=0;n<=2;n++){//Recorre todas las posibilidades del array
            for (int m=0;m<=2;m++){
                if (control[n][m]==0){//Si esta vacia
                    control[n][m]=1;//Añade posicion del jugador x
                    aux=max();//Llama al metodo del jugador X
                    if (aux<v) v=aux; //Igual que max()   
                    control[n][m]=0;//Quita la ficha que ha puesto despues de comprobar
                }
            }
        }
        return v;
    }
	
	@Override
	public boolean onCreateOptionsMenu(Menu menu) {
		// Inflate the menu; this adds items to the action bar if it is present.
		getMenuInflater().inflate(R.menu.main, menu);
		return true;
	}

}
